package systemRegistry

import (
	"fmt"
	"log"
	"strings"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
	"golang.org/x/sys/windows/registry"
)

var regKey registry.Key

func openSystemRegistry() {
	key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager\Environment`,
		registry.QUERY_VALUE|registry.SET_VALUE|registry.ENUMERATE_SUB_KEYS)
	if err != nil {
		log.Println("无法打开注册表项: %v", err)
		windows.Exit(1)
	}
	regKey = key
}

func openUserRegistry() {
	key, err := registry.OpenKey(registry.CURRENT_USER, `Environment`,
		registry.QUERY_VALUE|registry.SET_VALUE|registry.ENUMERATE_SUB_KEYS)
	if err != nil {
		log.Println("无法打开注册表项: %v", err)
		windows.Exit(1)
	}
	regKey = key
}

func QuerySystemGoHome() string {
	value := queryGoHome()
	defer regKey.Close()
	return value
}

func queryGoHome() string {
	openSystemRegistry()
	value, _, err := regKey.GetStringValue("GO_HOME")
	if err != nil {
		defer regKey.Close()
		openUserRegistry()
		value, _, err = regKey.GetStringValue("GO_HOME")
		if err != nil {
			defer regKey.Close()
			log.Println("读取注册表失败: %v", err)
			log.Println("无法找到JAVA_HOME环境变量")
			openSystemRegistry()
			log.Println("打开系统环境变量")
			goProxyAndPath()
			log.Println("添加classpath和jdk path配置")
			return ""
		}
		return value
	}
	return value
}

func goProxyAndPath() {
	_, _, err := regKey.GetStringValue("GOPROXY")
	if err != nil {
		addEnvironmentVariable(regKey, "GOPROXY", "https://goproxy.cn/", false)
	}
	val, _, _ := regKey.GetStringValue("Path")
	if !strings.Contains(val, "%GO_HOME%\\bin") {
		addEnvironmentVariable(regKey, "Path", "%GO_HOME%\\bin", true)
	}
}

func SetSysGoHome(path string) {
	queryGoHome()
	addEnvironmentVariable(regKey, "GO_HOME", path, false)
	defer regKey.Close()
}

// 添加或更新环境变量
func addEnvironmentVariable(key registry.Key, name, value string, append bool) error {
	if append {
		// 检查变量是否已存在
		existingValue, _, err := key.GetStringValue(name)
		if err == nil {
			// 处理PATH变量的特殊情况
			if name == "Path" {
				// 检查是否已包含该路径
				if !strings.Contains(existingValue, value) {
					// 添加分号分隔符
					if !strings.HasSuffix(existingValue, ";") {
						existingValue += ";"
					}
					value = existingValue + value
				} else {
					fmt.Printf("PATH变量已包含路径 %s\n", value)
					return nil
				}
			} else {
				// 普通变量追加
				value = existingValue + value
			}
		}
	}

	// 设置注册表值
	return key.SetStringValue(name, value)
}

// 删除环境变量
func deleteEnvironmentVariable(key registry.Key, name string) error {
	// 检查变量是否存在
	_, _, err := key.GetStringValue(name)
	if err != nil {
		if err == registry.ErrNotExist {
			fmt.Printf("环境变量 %s 不存在，无需删除\n", name)
			return nil
		}
		return err
	}

	// 删除注册表值
	return key.DeleteValue(name)
}

// 通知系统环境变量已更改
func NotifyEnvironmentChanged() error {
	// 此部分代码省略，与错误无关
	// 加载user32.dll
	user32, err := syscall.LoadDLL("user32.dll")
	if err != nil {
		fmt.Println("无法加载user32.dll:", err)
		return err
	}

	// 获取SendMessageTimeoutA函数
	sendMessageTimeout, err := user32.FindProc("SendMessageTimeoutA")
	if err != nil {
		fmt.Println("无法找到SendMessageTimeoutA函数:", err)
		return err
	}

	// 定义常量
	const (
		WM_SETTINGCHANGE = 0x001A
		SMTO_ABORTIFHUNG = 0x0002
	)

	// 广播环境变量更改消息  unsafe.Pointer
	result, _, _ := sendMessageTimeout.Call(
		0xFFFF, // HWND_BROADCAST
		WM_SETTINGCHANGE,
		0,
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Environment"))),
		SMTO_ABORTIFHUNG,
		5000, // 超时时间（毫秒）
		0,
	)
	if result == 0 {
		fmt.Println("发送环境变量更改通知失败")
	} else {
		fmt.Println("已通知系统环境变量已更改")
		fmt.Println("注意：某些应用程序可能需要重启才能使用新的环境变量")
	}
	return nil
}
